//This 2d3d browser use the chrome module and mouse and keyboard inputs are working in this one.
AddCSLuaFile("shared.lua")

ENT.Base = "base_anim"
ENT.Type = "anim"

ENT.RenderGroup = RENDERGROUP_BOTH

local activebrowser = nil
MatInUse = {}

function MakeRT(ENT, RTname, RTsize, Additive)
	ENT.RTarget = GetRenderTarget(RTname, RTsize, RTsize, Additive)
	ENT.RTargetName = RTname
	ENT.RTargetSize = RTsize
end

function SetupBrowserMat(ENT, mat, mousetex, width, height, screenwidth, screenheight, format, scale)
	if SERVER then return end
	require("chrome")

	ENT.Mat = mat
	ENT.BrowserMat = Material(mat)
	ENT.TexId = surface.GetTextureID(mat)
	ENT.BrowserMat2 = CreateMaterial(ENT.RTargetName,"UnlitGeneric",
		{
			["$vertexcolor"] = 1,
		}
	)
	ENT.BrowserMat2:SetMaterialTexture("$basetexture", ENT.RTarget)
	ENT.BrowserTex2 = ENT.BrowserMat:GetMaterialTexture("$basetexture")

	ENT.BrowserTex = ENT.BrowserMat:GetMaterialTexture("$basetexture")
	--ENT.BrowserTex = ENT.RTarget

	ENT.MouseMat = mousetex
	ENT.MouseMaterial = Material(mousetex)
	ENT.MouseTexture = ENT.MouseMaterial:GetMaterialTexture("$basetexture")
	ENT.MouseTexId = surface.GetTextureID(mousetex)

	if !ENT.BrowserTex then
		Error("Invalid Material " .. tostring(mat))
	end

	if !ENT.MouseTexture then
		Error("Invalid Cursor Material " .. tostring(mousetex))
	end

	ENT.TexWidth = ENT.BrowserTex:GetActualWidth()
	ENT.TexHeight = ENT.BrowserTex:GetActualHeight()
	ENT.Tex2Width = ENT.BrowserTex2:GetActualWidth()
	ENT.Tex2Height = ENT.BrowserTex2:GetActualHeight()
	ENT.MouseTexWidth = ENT.MouseTexture:GetActualWidth()
	ENT.MouseTexHeight = ENT.MouseTexture:GetActualHeight()
	ENT.Width = width
	ENT.Height = height
	ENT.SWidth = 1 / (screenwidth * scale)
	ENT.SHeight = 1 / (screenheight * scale)
	ENT.Format = format
	ENT.Scale = scale
	MatInUse[mat] = false
end

local function RayQuadIntersect(vOrigin, vDirection, vPlane, vX, vY)
	local vp = vDirection:Cross(vY)

	local d = vX:DotProduct(vp)

	if (d <= 0.0) then return end

	local vt = vOrigin - vPlane
	local u = vt:DotProduct(vp)
	if (u < 0.0 or u > d) then return end

	local v = vDirection:DotProduct(vt:Cross(vX))
	if (v < 0.0 or v > d) then return end

	return Vector(u / d, v / d, 0)
end

local function BuildFace(vMins, vMaxs)
	local p3 = Vector(0, vMaxs.y, vMins.z)
	local p4 = Vector(0, vMins.y, vMins.z)
	local p7 = Vector(0, vMaxs.y, vMaxs.z)
	local p8 = Vector(0, vMins.y, vMaxs.z)

	return
	{
		Vertex( p8, 0, 0 ),
		Vertex( p7, 1, 0 ),
		Vertex( p4, 0, 1 ),
		Vertex( p7, 1, 0 ),
		Vertex( p3, 1, 1 ),
		Vertex( p4, 0, 1 ),
	}
end

function ENT:SetLargeBounds()
	local w = self.Width / 2
	local min = Vector(-w * self.Scale, -w * self.Scale, 0)
	local max = Vector(w * self.Scale, w * self.Scale, self.Height * self.Scale)

	self:SetRenderBounds(min, max)
end


function ENT:BaseBrowserDraw(urltxt, C1, C2)

	local ShowURLbeam = HideURLbeam

	--self.Browser:Update()

	-- OldTex ITexture
	-- self.RTarget ITexture
	-- self.Mat string
	-- self.BrowserMat IMaterial
	-- self.BrowserTex ITexture
	-- self.TexId number

	local oldw = ScrW()
	local oldh = ScrH()

	local NewRT = self.RTarget
	local OldRT = render.GetRenderTarget()

	render.SetRenderTarget(NewRT)
	render.SetViewPort(0, 0, self.Width, self.Height)
	--render.Clear( 255, 255, 255, 255, true )

	cam.Start2D()
		surface.SetTexture(self.TexId)
		surface.SetDrawColor(255, 255, 255, 255)
		surface.DrawTexturedRect(0,0, self.TexWidth, self.TexHeight)

		local TextColor = C1 
		local TextBgColor = C2

		draw.RoundedBox(16, 5, 5, self.Width-10, 40, TextBgColor)

		--surface.CreateFont("arial",10,400,true,false,"Browser_Small")
		surface.CreateFont("arial",30,400,true,false,"Browser_Default")
		--surface.CreateFont("arial",60,400,true,false,"Browser_Big")

		surface.SetTextColor(TextColor)
		surface.SetFont("Browser_Default")
		local Turl = urltxt or ""
		if (string.len(urltxt or "") > 68) then
			Turl = (string.Left(urltxt or "", 65) .. "...")
		else
			Turl = urltxt or ""
		end
		local Tw, Th = surface.GetTextSize("URL: " ..Turl)
		surface.SetTextPos(math.Clamp(((self.Width / 2) - (Tw / 2)), 10, self.Width / 2), 10)
		surface.DrawText("URL: " ..Turl)
	cam.End2D()

	render.SetViewPort(0, 0, oldw, oldh)
	render.SetRenderTarget(OldRT)

	local pos, ang = self:GetPosBrowser(), self:GetAngles()
	local up, right = self:GetUp(), self:GetRight()

	pos = pos + (up * self.Height * self.Scale) + (right * (self.Width/2) * self.Scale)

	ang:RotateAroundAxis(ang:Up(), 90)
	ang:RotateAroundAxis(ang:Forward(), 90)

	cam.Start3D2D(pos,ang,self.Scale)
		self:DrawBrowser()
		self:DrawCursor()
	cam.End3D2D()
end

function ENT:DrawBrowser()
	surface.SetMaterial(self.BrowserMat2)
	surface.SetDrawColor(255, 255, 255, 255)
	self:DrawTexturedRectScaled(0, 0, self.Tex2Width, self.Tex2Height / self.Format, math.Clamp(self.Tex2Width / self.RTargetSize, 0, 1), math.Clamp((self.Tex2Height / self.Format) / self.RTargetSize, 0, 1))
end

function ENT:DrawCursor()
	if !self.mActive then return end

	surface.SetDrawColor(255, 255, 255, 255)
	surface.SetTexture(self.MouseTexId)
	surface.DrawTexturedRect(self.mX - 1, self.mY - 1, self.MouseTexWidth / 16, self.MouseTexHeight / 16)
end

local POLYGON = {{{},{},{}},{{},{},{}}} -- Two polygons

local function SetVertexData(VERTEX,x,y,u,v)
	VERTEX.x = x
	VERTEX.y = y
	VERTEX.u = u
	VERTEX.v = v
end

function ENT:DrawTexturedRectScaled(x,y,w,h,x_scale,y_scale)
	local x_scale,y_scale = x_scale or 1,y_scale or 1
	--############ First Polygon
	--First Vertex - Top left
	SetVertexData(POLYGON[1][1],x,y,0,0)
	--Second Vertex - Top right
	SetVertexData(POLYGON[1][2],x+w,y,x_scale,0)
	--Third Vertex - Bottom left
	SetVertexData(POLYGON[1][3],x,y+h,0,y_scale)
	--############ Second Polygon
	--First Vertex - Top Right
	SetVertexData(POLYGON[2][1],x+w,y,x_scale,0)
	--Second Vertex - Bottom right
	SetVertexData(POLYGON[2][2],x+w,y+h,x_scale,y_scale)
	--Third Vertex - Bottom left
	SetVertexData(POLYGON[2][3],x,y+h,0,y_scale)
	surface.DrawPoly(POLYGON[1])
	surface.DrawPoly(POLYGON[2])
end

function ENT:InitBrowser()
	if !self.Mat then return end

	if MatInUse[self.Mat] then
		MatInUse[self.Mat]:RemoveBrowser()
	end
	self.Browser = chrome.NewBrowser(self.Width, self.Height, self.BrowserTex, self:GetTable())

	MatInUse[self.Mat] = self

	self.mX, self.mY = 0, 0
	self.mActive = false
end

function ENT:RemoveBrowser()
	if self.Browser then
		self.Browser:Free()
		self.Browser = false
		MatInUse[self.Mat] = false

		self:CloseInputPanel()
		if self.OnLeaveBrowser then
			self:OnLeaveBrowser()
		end
	end
end

function ENT:OnRemove()
	self:RemoveBrowser()
end

function ENT:GetPosBrowser()
	return self:GetPos()
end

function BrowserScroll(ply, bind, pressed)
	if !IsValid(activebrowser) || !activebrowser.Browser || !activebrowser.mActive then return end

	if bind == "invnext" then
		activebrowser.Browser:MouseScroll(-30)
		return true
	elseif bind == "invprev" then
		activebrowser.Browser:MouseScroll(30)
		return true
	end
end

hook.Add("PlayerBindPress", "BrowserScroll", BrowserScroll)

function ENT:MouseRayInteresct()
	local up, right = self:GetUp(), self:GetRight()
	local plane = self:GetPosBrowser() + ( (up * self.Height * self.Scale) + ( right * (-self.Width/2) * self.Scale ) )

	local x = (right * (self.Width/2) * self.Scale) - (right * (-self.Width/2) * self.Scale)
	local y = (up * -(self.Height * self.Scale))

	return RayQuadIntersect(LocalPlayer():EyePos(), LocalPlayer():GetCursorAimVector(), plane, x, y)
end

local mousedownlast = false

function ENT:MouseThink()
	local uv = self:MouseRayInteresct()

	if uv then
		if !self.mActive then
			if self.Focus then
				self:BringUpInputPanel()
			end
			if self.OnEnterBrowser then
				self:OnEnterBrowser()
			end
		end

		// there can only be one active browser, this is for scrolling
		activebrowser = self

		self.mActive = true
		self.mX, self.mY = (1-uv.x) * self.Width, uv.y * self.Height

		self.mX = math.Clamp(self.mX, 1, self.Width - 1)
		self.mY = math.Clamp(self.mY, 1, self.Height - 1)

		self.Browser:MouseMove(self.mX, self.mY)

		local down = input.IsMouseDown(MOUSE_LEFT)

		if down && !mousedownlast then
			self.Browser:MouseUpDown(true, 0)
		elseif !down && mousedownlast then
			self.Browser:MouseUpDown(false, 0)
		end

		mousedownlast = down

	elseif self.mActive then
		self.mActive = false
		self:CloseInputPanel()

		if self.OnLeaveBrowser then
			self:OnLeaveBrowser()
		end
	end
end

function ENT:BringUpInputPanel()
	if self.InputPanel then return end

	print("bring up input")
	self.InputPanel = vgui.Create("DTextEntry")
	self.InputPanel:NoClipping(true)
	self.InputPanel:MakePopup()
	self.InputPanel:SetMouseInputEnabled(false)
	self.InputPanel.DownKey = {}

	self.InputPanel.AllowInput = function(panel, strValue)
		self.Browser:KeyEvent(string.byte(strValue), true)
		return false
	end

	self.InputPanel.Think = function(panel)
		// this is so we can "hold down" a key

		for key, down in pairs(panel.DownKey) do
			if !input.IsKeyDown(key) then
				self.Browser:KeyEvent(key, false, true)
				panel.DownKey[key] = nil
			end
		end
	end

	self.InputPanel.OnKeyCodePressed = function(panel, code)
		self.Browser:KeyEvent(code, true, true)
		panel.DownKey[code] = true
		panel.RepeatKey = RealTime()

		if code == KEY_TAB || code == KEY_ENTER then
			self:CloseInputPanel()
		end
	end

	self.InputPanel.Paint = function(panel)
		draw.SimpleText("Hit tab to regain control", "ScoreboardText", ScrW() / 2, 0, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
	end
end

function ENT:CloseInputPanel()
	if !self.InputPanel then return end

	print("close input")
	self.InputPanel:Remove()
	self.InputPanel = nil
end

function ENT:onChangeTargetURL(url, status)
	if self.ChangedTargetURL then
		self:ChangedTargetURL(url)
	end
end


function ENT:onBeginNavigation(url)
	if self.OpeningURL then
		self:OpeningURL(url)
	end
end

function ENT:onBeginLoading(url, status)
	if self.LoadingURL then
		self:LoadingURL(url, status)
	end
end

function ENT:onFinishLoading()
	if self.FinishLoading then
		self:FinishLoading()
	end
end

function ENT:onChangeFocus(focus)
	print("focus", focus, self.InputPanel)
	if focus then
		self:BringUpInputPanel()
	else
		self:CloseInputPanel()
	end
	self.Focus = focus
end